package com.insight.repository;

import com.insight.entity.MetadataColumn;
import com.insight.entity.MetadataTable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * T048: MetadataColumn Repository接口
 * 列元数据数据访问层,使用Spring Data JPA
 *
 * @author Insight Team
 */
@Repository
public interface MetadataColumnRepository extends JpaRepository<MetadataColumn, Long> {

    /**
     * 根据表查找所有列元数据
     *
     * @param table 表
     * @return 列元数据列表
     */
    List<MetadataColumn> findByTable(MetadataTable table);

    /**
     * 根据表ID查找所有列元数据
     *
     * @param tableId 表ID
     * @return 列元数据列表
     */
    @Query("SELECT mc FROM MetadataColumn mc WHERE mc.table.id = :tableId")
    List<MetadataColumn> findByTableId(@Param("tableId") Long tableId);

    /**
     * 根据表和列名查找列元数据
     *
     * @param table      表
     * @param columnName 列名
     * @return 列元数据Optional
     */
    Optional<MetadataColumn> findByTableAndColumnName(MetadataTable table, String columnName);

    /**
     * 根据表ID和列名查找列元数据
     *
     * @param tableId    表ID
     * @param columnName 列名
     * @return 列元数据Optional
     */
    @Query("SELECT mc FROM MetadataColumn mc WHERE mc.table.id = :tableId AND mc.columnName = :columnName")
    Optional<MetadataColumn> findByTableIdAndColumnName(@Param("tableId") Long tableId, @Param("columnName") String columnName);

    /**
     * 根据表和列位置查找列元数据
     * 按照列位置升序排列
     *
     * @param table 表
     * @return 列元数据列表
     */
    List<MetadataColumn> findByTableOrderByColumnPositionAsc(MetadataTable table);

    /**
     * 根据表ID和列位置查找列元数据
     * 按照列位置升序排列
     *
     * @param tableId 表ID
     * @return 列元数据列表
     */
    @Query("SELECT mc FROM MetadataColumn mc WHERE mc.table.id = :tableId ORDER BY mc.columnPosition ASC")
    List<MetadataColumn> findByTableIdOrderByColumnPositionAsc(@Param("tableId") Long tableId);

    /**
     * 根据数据类型查找列元数据
     *
     * @param dataType 数据类型
     * @return 列元数据列表
     */
    List<MetadataColumn> findByDataType(String dataType);

    /**
     * 根据表和数据类型查找列元数据
     *
     * @param table    表
     * @param dataType 数据类型
     * @return 列元数据列表
     */
    List<MetadataColumn> findByTableAndDataType(MetadataTable table, String dataType);

    /**
     * 查找表中的主键列
     *
     * @param table 表
     * @return 主键列元数据列表
     */
    List<MetadataColumn> findByTableAndIsPrimaryKeyTrue(MetadataTable table);

    /**
    /**
     * 查找表中的可空列
     *
     * @param table 表
     * @return 可空列元数据列表
     */
    List<MetadataColumn> findByTableAndNullableTrue(MetadataTable table);

    /**
     * 查找表中的非空列
     *
     * @param table 表
     * @return 非空列元数据列表
     */
    List<MetadataColumn> findByTableAndNullableFalse(MetadataTable table);

    /**
     * 分页查询指定表的列元数据
     *
     * @param table    表
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    Page<MetadataColumn> findByTable(MetadataTable table, Pageable pageable);

    /**
     * 分页查询指定表ID的列元数据
     *
     * @param tableId  表ID
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    @Query("SELECT mc FROM MetadataColumn mc WHERE mc.table.id = :tableId")
    Page<MetadataColumn> findByTableId(@Param("tableId") Long tableId, Pageable pageable);

    /**
     * 查找指定时间范围内更新的列元数据
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 列元数据列表
     */
    List<MetadataColumn> findByUpdatedAtBetween(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 查找指定表在时间范围内更新的列元数据
     *
     * @param table     表
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 列元数据列表
     */
    List<MetadataColumn> findByTableAndUpdatedAtBetween(MetadataTable table, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计指定表的列数量
     *
     * @param table 表
     * @return 列数量
     */
    long countByTable(MetadataTable table);

    /**
     * 统计指定表ID的列数量
     *
     * @param tableId 表ID
     * @return 列数量
     */
    @Query("SELECT COUNT(mc) FROM MetadataColumn mc WHERE mc.table.id = :tableId")
    long countByTableId(@Param("tableId") Long tableId);

    /**
     * 统计指定表的主键列数量
     *
     * @param table 表
     * @return 主键列数量
     */
    long countByTableAndIsPrimaryKeyTrue(MetadataTable table);

    /**
     * 检查列是否存在
     *
     * @param table      表
     * @param columnName 列名
     * @return 是否存在
     */
    boolean existsByTableAndColumnName(MetadataTable table, String columnName);

    /**
     * 删除指定表的所有列元数据
     *
     * @param table 表
     */
    void deleteByTable(MetadataTable table);

    /**
     * 删除指定表ID的所有列元数据
     *
     * @param tableId 表ID
     */
    @Modifying
    @Transactional
    @Query("DELETE FROM MetadataColumn mc WHERE mc.table.id = :tableId")
    void deleteByTableId(@Param("tableId") Long tableId);

    /**
     * 批量保存列元数据
     * 重写saveAll方法以优化批量插入性能
     *
     * @param columns 列元数据列表
     * @return 保存后的列元数据列表
     */
    @Override
    <S extends MetadataColumn> List<S> saveAll(Iterable<S> columns);

    // ==================== US4: 元数据搜索功能 (T100) ====================

    /**
     * 根据列名搜索列元数据 (模糊匹配)
     * 使用LIKE进行简单模糊搜索
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    @Query("SELECT mc FROM MetadataColumn mc WHERE LOWER(mc.columnName) LIKE LOWER(CONCAT('%', :keyword, '%'))")
    Page<MetadataColumn> searchByColumnName(@Param("keyword") String keyword, Pageable pageable);

    /**
     * 根据列注释搜索列元数据 (模糊匹配,支持中文)
     * 使用LIKE进行简单模糊搜索
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    @Query("SELECT mc FROM MetadataColumn mc WHERE mc.columnComment LIKE CONCAT('%', :keyword, '%')")
    Page<MetadataColumn> searchByColumnComment(@Param("keyword") String keyword, Pageable pageable);

    /**
     * 根据数据类型查找列元数据 (分页)
     * 精确匹配数据类型
     *
     * @param dataType 数据类型
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    @Query("SELECT mc FROM MetadataColumn mc WHERE mc.dataType = :dataType")
    Page<MetadataColumn> findByDataType(@Param("dataType") String dataType, Pageable pageable);

    /**
     * 根据表和数据类型查找列元数据 (分页)
     * 用于组合搜索场景: 指定表 + 指定数据类型
     *
     * @param table    表
     * @param dataType 数据类型
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    @Query("SELECT mc FROM MetadataColumn mc WHERE mc.table = :table AND mc.dataType = :dataType")
    Page<MetadataColumn> findByTableAndDataType(
            @Param("table") MetadataTable table,
            @Param("dataType") String dataType,
            Pageable pageable);
}
